package com.example.tms.tools;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.example.tms.annotation.MonitorRequest;
import com.example.tms.bean.OrderMgmt;
import com.example.tms.bean.SysLog;
import com.example.tms.bean.UserInfo;
import com.example.tms.bean.UserView;
import com.example.tms.mapper.OrderMapper;
import com.example.tms.mapper.SysLogMapper;
import jdk.nashorn.internal.objects.Global;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

@Component
@Aspect
public class ControllerAOP {
    @Autowired
    private SysLogMapper sysLogMapper;
    @Autowired
    private OrderMapper orderMapper;
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

/*@Pointcut("@within(com.example.tms.controller.AdviceAnnotation)")
    public void executeService(){

}*/
@Before(value = "@annotation(com.example.tms.annotation.MonitorRequest)")
    public void beforeAdvice(JoinPoint jp){
   /* logger.info("------前置处理通知开始---------");
 Object[] obj = jp.getArgs();
 if(obj.length>0){
     logger.info("所有参数为：{}" ,JSON.toJSON(obj));
 }
  *//*  RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
    HttpServletRequest req = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
  *//**//*  //要获取session
    HttpSession session = (HttpSession) requestAttributes.resolveReference(RequestAttributes.REFERENCE_SESSION);
    //拿到session，就可以取当前登陆用户信息，进行一系列的校验
    logger.info("SessionID{}",session.getId());*//**//*
    Enumeration<String> enumMap = req.getParameterNames();
    Map<String,String> params = new HashMap<String,String>();
    while(enumMap.hasMoreElements()){
        String param = enumMap.nextElement();
        params.put(param,req.getParameter(param));
        logger.info("键值对参数:{}={}",param,req.getParameter(param));
    }*//*
    logger.info("------前置处理通知结束---------");*/
    // 接收到请求，记录请求内容
    try {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        Subject subject = SecurityUtils.getSubject();
        UserView userView = (UserView) subject.getPrincipal();
        /*// 记录下请求内容
        logger.info("URL : " + request.getRequestURL().toString());
        logger.info("HTTP_METHOD : " + request.getMethod());
        logger.info("IP : " + request.getRemoteAddr());
        logger.info("CLASS_METHOD : " + jp.getSignature().getDeclaringTypeName() + "." + jp.getSignature().getName());
        logger.info("ARGS : " + Arrays.toString(jp.getArgs()));*/
        logger.info("--------------------前置通知开始");
        logger.info("{userName : "+ userView.getYhm()+" , realName : "+userView.getZsxm()+" , URL : "+request.getRequestURL().toString()+" , HTTP_METHOD : "+request.getMethod()+" , IP : "+request.getRemoteAddr()+" , CLASS_METHOD : "+ jp.getSignature().getDeclaringTypeName() + "." + jp.getSignature().getName()+" , ARGS : "+ JSONArray.toJSONString(jp.getArgs())+"}");
//获取操作
        //从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) jp.getSignature();
        Method method = signature.getMethod();
        MonitorRequest myLog = method.getAnnotation(MonitorRequest.class);
        SysLog sysLog = new SysLog();
        if (myLog != null) {
            String type = myLog.type();
            String description = myLog.description();
            if(type.equals("order")){
                sysLog.setUsername(userView.getYhm());
                sysLog.setRealName(userView.getZsxm());
                String[] buff = description.split(" ");
                sysLog.setOperationPart(buff[0]);
                sysLog.setOperation(buff[1]);
                OrderMgmt order = orderMapper.findByDdid((String)jp.getArgs()[0]);
                if(order!=null){
                    sysLog.setParams(order.getDdh());
                }else{

                }
                sysLog.setIp(request.getRemoteAddr());
                sysLog.setCreateDate(GlobalParam.getTime());
                sysLogMapper.saveAndFlush(sysLog);
            }
        }

    }catch (Exception e){
        e.printStackTrace();
    }



}

 @After(value = "@annotation(com.example.tms.annotation.MonitorRequest)")
    public void doAfterAdvice(JoinPoint joinPoint){
/*    logger.info("-------后置通知开始-------");
     logger.info("-------后置通知结束-------");*/
 }
    @AfterReturning(value = "@annotation(com.example.tms.annotation.MonitorRequest)",returning = "resultObj")
    public void afterAdviceReturn(Object resultObj){
       /* logger.info("-------后置返回通知总Object开始-------");*/
        logger.info("返回数据 : "+JSON.toJSONString(resultObj));
        logger.info("--------------------后置返回通知总Object结束");
    }
//    @AfterReturning(value = "executeService()",returning = "resultRes")
//    public void afterAdviceReturn(Object resultObj){
//        logger.info("-------后置返回通知总Object开始-------");
//        logger.info(JSON.toJSONString(resultObj));
//        logger.info("-------后置返回通知总Object结束-------");
//    }
@AfterThrowing(value = "@annotation(com.example.tms.annotation.MonitorRequest)",throwing = "exception")
    public  void afterAdviceThrowing(JoinPoint jp,Throwable exception){
    logger.info("-------后置异常总通知开始--------");
    if(exception instanceof NullPointerException){
        logger.info(jp.getSignature().getDeclaringTypeName()+"."+jp.getSignature().getName()+"()空指针异常");
    }else if(exception instanceof IndexOutOfBoundsException){
        logger.info(jp.getSignature().getDeclaringTypeName()+"."+jp.getSignature().getName()+"()越界异常");
    }
    logger.info("-------后置异常总通知结束--------");
}

}
